Coming from previous design of having all deltas be bidirectional

Current format for operations is tuple[ name, data] this isnt enforced its just what ive been doing

they are stored in a list as tuple[ type| None, list[ tuple[ transformOperationId, transformData]]]

version types can currently either be INIT| FULL| DELTA| FULL_WITH_DELTA if we had unidirectional deltas| we would have INIT| FULL| FORWARDS_DELTA| BIDIRECTIONAL_DELTA| FULL_WITH_BACKWARDS_DELTA

So calculateDeltaData needs to know the desired direction if we wish for a FULL_WITH_BACKWARDS_DELTA save then we desire a backwards delta otherwise we want a normal delta save and so

so the save function takes a desired: FORWARDS_DELTA| BIDIRECTIONAL_DELTA| FULL_WITH_BACKWARDS_DELTA and calls calculateDeltaData with a desired TransformType of FORWARDS| BIDIRECTIONAL| BACKWARDS

calculateDeltaData does some initial checks and returns and then finds a ConstructionSet for the type the ConstructionSet.deltaConstruction takes the two instances and returns ( TransformType, data) they could take a preferred TransformType which is None by default one way they could implement this is that when detaConstruction encounters a situation which could result in branching types of TransformType it uses the preferred Every operation needs to support bidirectional, ( forwards, backwards) but some may store the data in the same manner In this case, deltaConstruction can return bidirecitonal as this signals that the most traversible option is available


deconstructVersionDataChain and applyDataTransform need to change

deconstructVersionDataChain will still return a valid sequence but it will possibly be made of uni and bidirectional deltas when applying data changes in a line now, we will encounter unidirectional deltas

class Directionality( IntFlag):
	BIDIRECTIONAL= auto()
	UNIDIRECTIONAL= auto()

the ConstructionSet s can now have a function called applyDeltas which takes a group of delta transforms of a specific directionality applyDataTransform currently takes typeAndTransforms: deltaTransforms it only needs to take the type once, as it should only ever be passed operations from a singular type so it should take ( object: Any, typez: type, operations: Sequence[ Sequence[ Directionality, Sequence[ Sequence[ transformOperationId, transformData]]]], direction: OperationDirection) and within it should call ConstructionSet.applyDeltas for each Directionality block so ConstructionSet.applyDeltas should take ( object: Any, directionality: , operations: Sequence[ Sequence[ transformOperationId, transformData]])


The design of preferred type passing seems a little weak

We can specify either a transform type or a commit type

Transform type delta s are BIDIRECTIONAL| UNIDIRECTIONAL| NONE| FULL Commit types are those specified above, INIT| FULL| FORWARDS_DELTA| BIDIRECTIONAL_DELTA| FULL_WITH_BACKWARDS_DELTA

constructed bidirectional transforms

when specifying the preferred do we specify q to w? or w to q if no preferred and only bidirectional like before it is implied q to w forwards and w to q backwards so maybe bidirectional needs an application direction of q to w or w to q unidirectional are constructed with a specific direction

i think in some circumstances if the preferred isnt available then we want to fallback to a full change in others we could accept bidirectional in place of unidirectional, unidirectional in place of bidirectional, maybe these desires could be fully specified using a sequence of acceptable outcomes, and if none can be fulfilled then it falls to a full change there is fallback behaviour for no sequence specified

the issue with running it once, determining the output and then rerunning is that the conversion set may have to run extra processes whereas if the order of desired outcomes was known to the conversion function then it could quickly decide on the outcome. maybe then a preference can be specified as well as a fallback value which either falls back to the other directionality than the prefferred and then to full or it directly falls back to a full transform so

class TransformFallback( IntFlag):
	OPPOSITE_DIRECTIONALITY_THEN_FULL= auto()
	FULL= auto()

So LTSD.save can take a preffered version type from these specific CommitType s: FORWARDS_DELTA| BIDIRECTIONAL_DELTA| FULL_WITH_BACKWARDS_DELTA if forwards then we desire a unidirectional delta, if none can be found then we could fall back to bidirectional or full, either one really save could take a fallback value it is currently relativelty unknown where it will be called from to initiate the different commit types, i envision an optimisation process which could reduce load times by constructing FULL_WITH_BACKWARDS_DELTA commits on data that has a large amount of subsequent deltas, bidirectional or forward could be discerned between by a software aspect seeking to optimise each individual version, maybe one that doesnt care about backwards traversing on the data could only use FORWARDS_DELTA

calculateDeltaData can take a preffered delta transform type form these TransformType s: UNIDIRECTIONAL| BIDIRECTIONAL as well as a fallback of any from TransformFallback

DeltaTransformSet.deltaConstruction can take a preffered delta transform type form these TransformType s: UNIDIRECTIONAL| BIDIRECTIONAL as well as a fallback of any from TransformFallback

UNIDIRECTIONAL s are calculated as q to w BIDIRECTIONAL s can be applied as ( q to w)| ( w to q)

So now need to redesign save, calculateDeltaData, DeltaTransformSet.deltaConstruction save needs to call calculateDeltaData with UNIDIRECTIONAL if FORWARDS_DELTA needs to call calculateDeltaData with BIDIRECTIONAL if BIDIRECTIONAL_DELTA needs to call calculateDeltaData with UNIDIRECTIONAL if FULL_WITH_BACKWARDS_DELTA

How the output is managed is dependant on the transform type of the output as well as the preferred CommitType passed to save FULL, NONE, BIDIRECTIONAL is the same result regardless if the resultant TransformType is UNIDIRECTIONAL then: if the preffered CommitType is FORWARDS then we are just using the returned data as a forwards delta if the preffered CommitType is FULL_WITH_BACKWARDS then we need to use the full data and the returned data

calculateDeltaData is mostly a passthrough to either basic returns or DeltaTransformSet.deltaConstruction

DeltaTransformSet.deltaConstruction can return: tuple[ TransformType, tuple[ type| None, list[ tuple[ transformOperationId, transformData]]]| None| Any]

This doesnt need to change delta transforms of both directionalities can return list[ tuple[ transformOperationId, transformData]]] all elements of the sequence should be of the same directionality this includes any recursively contained delta lists Due to this recursive requirement, if the passed fallback to the containing level is FULL then that also must be the case for the called contained If the contained cannot match the prefference of the container then if FULL is active then the contained must not default to the opposite of the preferred delta type if OPPOSITE_DIRECTIONALITY_THEN_FULL is active then the containd should fallback to the opposite of the preffered and then full

i think this means that the contained fallback should match the fallback of the container

the preffered of the contained should match the preferred of the container if this is enforced by calculateDeltaData then we should be fine with just specifying the input prefferred and fallback for the contained

in the future it could also be made so that individual transforms in the delta list are either uni or bi directional